/*
    Copyright 2006-2012 Patrik Jonsson, sunrise@familjenjonsson.org

    This file is part of Sunrise.

    Sunrise is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    Sunrise is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Sunrise.  If not, see <http://www.gnu.org/licenses/>.

*/

/*! \file 
  Definition of the octogrid class.
*/

// (This file is included automatically by grid.h)


#include "blitz/array.h"
#include "vecops.h"

/** Class defining an octree. It just contains 8 subcells. */
template <typename cell_data_type >
class mcrx::octogrid
{
public:
  typedef mcrx::T_float T_float;
  typedef grid_cell<cell_data_type> T_cell;
  typedef typename T_cell::T_cell_tracker T_cell_tracker;
  typedef cell_data_type T_data;
  friend class grid_cell<cell_data_type> ;
  template<typename cdt> friend class adaptive_grid;

  friend class grid_cell<T_data>;
  friend class cell_tracker<T_data>;

protected:

  /// The cells are stored directly here since we know there are 8 of them.
  T_cell cells_[8];

  /// "Virtual constructor" used for creating appropriate sub grids.
  static octogrid* create_sub (int task) {
    return new octogrid (task);
  };
  /// Placement new version of the virtual constructor.
  static octogrid* create_sub (int task, void*& placement) {
    void* const p = placement;
    reinterpret_cast<octogrid*&> (placement) ++;
    return new (p) octogrid (task);
  };
  
  T_cell* get_cell(uint8_t oct) { return cells_+oct; };

public:
  explicit octogrid (int);
  ~octogrid () {};

  void placement_new_destructor ();

  static 
  void calculate_work_recursive(std::vector<bool>::const_iterator&,
				const std::vector<bool>::const_iterator&,
				vec3d, vec3d, std::vector<int>&, int, int);
};

/** Creates an octogrid. The tasks of the cells are set as specified. */
template < typename cell_data_type >
mcrx::octogrid<cell_data_type>::
octogrid (int task)
{
  for(int i=0; i<8; ++i) {
    cells_[i]=T_cell(task);
  }
}


/** Kind-of destructor.  This interesting construct is necessary since
    if we have allocated the grid using placement new, we can't let
    the destructors call delete.  So, we have to go through the data
    before, explicitly call the destructor for the substructure, set
    the pointer to 0 and THEN destruct ourselves.  */
template < typename cell_data_type >
void
mcrx::octogrid<cell_data_type>::placement_new_destructor ()
{
  for(int i=0; i<8; ++i) {
    cells_[i].placement_new_destructor();
  }
}

